using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace GenerativeAgents.Core
{
    /// <summary>
    /// 记忆系统主控制器
    /// 协调空间记忆、联想记忆和短期记忆的管理
    /// </summary>
    public class MemorySystem : MonoBehaviour
    {
        [Header("记忆系统配置")]
        [SerializeField] private int maxAssociativeMemories = 1000;
        [SerializeField] private float memoryDecayRate = 0.99f;
        [SerializeField] private int maxRetrievalResults = 10;
        [SerializeField] private bool enableMemoryLogging = false;
        
        [Header("记忆权重配置")]
        [SerializeField] private float recencyWeight = 0.3f;
        [SerializeField] private float importanceWeight = 0.3f;
        [SerializeField] private float relevanceWeight = 0.4f;
        
        // 记忆子系统
        public SpatialMemory SpatialMemory { get; private set; }
        public AssociativeMemory AssociativeMemory { get; private set; }
        public ScratchMemory ScratchMemory { get; private set; }
        
        // 组件引用
        private IEmbeddingEngine embeddingEngine;
        private DataPersistence dataPersistence;
        
        // 记忆统计
        private int totalMemoriesStored = 0;
        private int totalMemoriesRetrieved = 0;
        
        // 事件
        public event System.Action<MemoryNode> OnMemoryStored;
        public event System.Action<List<MemoryNode>> OnMemoryRetrieved;
        public event System.Action<string> OnMemoryExpired;
        
        private void Awake()
        {
            InitializeMemorySystem();
        }
        
        private void Start()
        {
            LoadPersistedMemories();
        }
        
        private void OnDestroy()
        {
            SaveMemoriesToPersistence();
        }
        
        /// <summary>
        /// 初始化记忆系统
        /// </summary>
        private void InitializeMemorySystem()
        {
            // 创建子系统
            SpatialMemory = new SpatialMemory();
            AssociativeMemory = new AssociativeMemory(maxAssociativeMemories);
            ScratchMemory = new ScratchMemory();
            
            // 获取组件引用
            embeddingEngine = GetComponent<IEmbeddingEngine>();
            dataPersistence = GetComponent<DataPersistence>();
            
            if (enableMemoryLogging)
            {
                Debug.Log("[MemorySystem] Memory system initialized");
            }
        }
        
        /// <summary>
        /// 存储事件到记忆系统
        /// </summary>
        public void StoreEvent(AgentEvent agentEvent)
        {
            try
            {
                // 创建记忆节点
                var memoryNode = MemoryNode.FromEvent(agentEvent);
                
                // 存储到联想记忆
                AssociativeMemory.AddMemory(memoryNode);
                
                // 更新空间记忆
                UpdateSpatialMemoryFromEvent(agentEvent);
                
                // 更新短期记忆
                ScratchMemory.UpdateFromEvent(agentEvent);
                
                // 更新统计
                totalMemoriesStored++;
                
                // 触发事件
                OnMemoryStored?.Invoke(memoryNode);
                
                if (enableMemoryLogging)
                {
                    Debug.Log($"[MemorySystem] Stored memory: {memoryNode.content} (Importance: {memoryNode.poignancy})");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[MemorySystem] Error storing event {agentEvent.eventId}: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 存储思想记忆
        /// </summary>
        public void StoreThought(string thought, int importance, Vector3 location, string locationName = "")
        {
            try
            {
                var thoughtNode = MemoryNode.CreateThought(thought, importance, location, locationName);
                
                // 生成嵌入向量
                if (embeddingEngine != null)
                {
                    thoughtNode.embedding = embeddingEngine.GenerateEmbedding(thought);
                }
                
                AssociativeMemory.AddMemory(thoughtNode);
                
                totalMemoriesStored++;
                OnMemoryStored?.Invoke(thoughtNode);
                
                if (enableMemoryLogging)
                {
                    Debug.Log($"[MemorySystem] Stored thought: {thought} (Importance: {importance})");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[MemorySystem] Error storing thought: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 存储计划记忆
        /// </summary>
        public void StorePlan(string planContent, DateTime scheduledTime, Vector3 targetLocation, string locationName = "")
        {
            try
            {
                var planNode = MemoryNode.CreatePlan(planContent, scheduledTime, targetLocation, locationName);
                
                // 生成嵌入向量
                if (embeddingEngine != null)
                {
                    planNode.embedding = embeddingEngine.GenerateEmbedding(planContent);
                }
                
                AssociativeMemory.AddMemory(planNode);
                
                totalMemoriesStored++;
                OnMemoryStored?.Invoke(planNode);
                
                if (enableMemoryLogging)
                {
                    Debug.Log($"[MemorySystem] Stored plan: {planContent}");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[MemorySystem] Error storing plan: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 检索记忆
        /// </summary>
        public List<MemoryNode> RetrieveMemories(string query, int k = -1)
        {
            if (k < 0) k = maxRetrievalResults;
            
            try
            {
                // 生成查询嵌入
                float[] queryEmbedding = null;
                if (embeddingEngine != null)
                {
                    queryEmbedding = embeddingEngine.GenerateEmbedding(query);
                }
                
                // 计算所有记忆的综合评分
                var scoredMemories = new List<(MemoryNode node, float score)>();
                
                foreach (var node in AssociativeMemory.GetAllMemories())
                {
                    if (node.CheckExpired()) continue; // 跳过过期记忆
                    
                    var score = CalculateMemoryScore(node, queryEmbedding, query);
                    scoredMemories.Add((node, score));
                }
                
                // 按分数排序并返回前k个
                var retrievedMemories = scoredMemories
                    .OrderByDescending(x => x.score)
                    .Take(k)
                    .Select(x => x.node)
                    .ToList();
                
                // 更新访问统计
                foreach (var memory in retrievedMemories)
                {
                    memory.Access();
                }
                
                totalMemoriesRetrieved += retrievedMemories.Count;
                OnMemoryRetrieved?.Invoke(retrievedMemories);
                
                if (enableMemoryLogging)
                {
                    Debug.Log($"[MemorySystem] Retrieved {retrievedMemories.Count} memories for query: {query}");
                }
                
                return retrievedMemories;
            }
            catch (Exception ex)
            {
                Debug.LogError($"[MemorySystem] Error retrieving memories for query '{query}': {ex.Message}");
                return new List<MemoryNode>();
            }
        }
        
        /// <summary>
        /// 基于查询对象检索记忆
        /// </summary>
        public List<MemoryNode> RetrieveMemories(MemoryQuery query)
        {
            try
            {
                var allMemories = AssociativeMemory.GetAllMemories();
                var filteredMemories = ApplyQueryFilters(allMemories, query);
                
                float[] queryEmbedding = null;
                if (embeddingEngine != null && !string.IsNullOrEmpty(query.queryText))
                {
                    queryEmbedding = embeddingEngine.GenerateEmbedding(query.queryText);
                }
                
                var scoredMemories = new List<(MemoryNode node, float score)>();
                
                foreach (var node in filteredMemories)
                {
                    if (node.CheckExpired()) continue;
                    
                    var score = CalculateMemoryScore(node, queryEmbedding, query.queryText, query);
                    scoredMemories.Add((node, score));
                }
                
                var retrievedMemories = scoredMemories
                    .OrderByDescending(x => x.score)
                    .Take(query.maxResults)
                    .Select(x => x.node)
                    .ToList();
                
                // 更新访问统计
                foreach (var memory in retrievedMemories)
                {
                    memory.Access();
                }
                
                totalMemoriesRetrieved += retrievedMemories.Count;
                OnMemoryRetrieved?.Invoke(retrievedMemories);
                
                return retrievedMemories;
            }
            catch (Exception ex)
            {
                Debug.LogError($"[MemorySystem] Error retrieving memories with query object: {ex.Message}");
                return new List<MemoryNode>();
            }
        }
        
        /// <summary>
        /// 计算记忆分数
        /// </summary>
        private float CalculateMemoryScore(MemoryNode node, float[] queryEmbedding, string query, MemoryQuery queryObj = null)
        {
            // 计算三个维度的分数
            var recencyScore = CalculateRecencyScore(node);
            var importanceScore = CalculateImportanceScore(node);
            var relevanceScore = CalculateRelevanceScore(node, queryEmbedding, query);
            
            // 使用配置的权重或查询对象的权重
            float rWeight = queryObj?.recencyWeight ?? recencyWeight;
            float iWeight = queryObj?.importanceWeight ?? importanceWeight;
            float relWeight = queryObj?.relevanceWeight ?? relevanceWeight;
            
            // 归一化并加权组合
            var normalizedRecency = NormalizeScore(recencyScore, 0, 1);
            var normalizedImportance = NormalizeScore(importanceScore, 1, 10);
            var normalizedRelevance = NormalizeScore(relevanceScore, -1, 1);
            
            return normalizedRecency * rWeight + normalizedImportance * iWeight + normalizedRelevance * relWeight;
        }
        
        /// <summary>
        /// 计算新近度分数
        /// </summary>
        private float CalculateRecencyScore(MemoryNode node)
        {
            var timeDiff = (DateTime.Now - node.lastAccessTime).TotalHours;
            return Mathf.Exp(-(float)timeDiff * 0.01f); // 指数衰减
        }
        
        /// <summary>
        /// 计算重要性分数
        /// </summary>
        private float CalculateImportanceScore(MemoryNode node)
        {
            return node.poignancy / 10f; // 归一化到0-1
        }
        
        /// <summary>
        /// 计算相关性分数
        /// </summary>
        private float CalculateRelevanceScore(MemoryNode node, float[] queryEmbedding, string query)
        {
            if (queryEmbedding != null && node.embedding != null && embeddingEngine != null)
            {
                return embeddingEngine.CalculateSimilarity(node.embedding, queryEmbedding);
            }
            
            // 后备方案：关键词匹配
            return CalculateKeywordSimilarity(node, query);
        }
        
        /// <summary>
        /// 计算关键词相似度
        /// </summary>
        private float CalculateKeywordSimilarity(MemoryNode node, string query)
        {
            if (string.IsNullOrEmpty(query) || node.keywords == null || node.keywords.Count == 0)
                return 0f;
            
            var queryWords = query.ToLower().Split(new char[] { ' ', '.', ',', '!', '?' }, StringSplitOptions.RemoveEmptyEntries);
            var matchCount = 0;
            
            foreach (var keyword in node.keywords)
            {
                if (queryWords.Any(word => word.Contains(keyword.ToLower()) || keyword.ToLower().Contains(word)))
                {
                    matchCount++;
                }
            }
            
            return matchCount / (float)Math.Max(node.keywords.Count, queryWords.Length);
        }
        
        /// <summary>
        /// 归一化分数
        /// </summary>
        private float NormalizeScore(float score, float min, float max)
        {
            if (max <= min) return 0f;
            return Mathf.Clamp01((score - min) / (max - min));
        }
        
        /// <summary>
        /// 应用查询过滤器
        /// </summary>
        private List<MemoryNode> ApplyQueryFilters(List<MemoryNode> memories, MemoryQuery query)
        {
            var filtered = memories.AsEnumerable();
            
            // 类型过滤
            if (query.typeFilter != null && query.typeFilter.Count > 0)
            {
                filtered = filtered.Where(m => query.typeFilter.Contains(m.type));
            }
            
            // 时间过滤
            if (query.timeAfter.HasValue)
            {
                filtered = filtered.Where(m => m.createdTime >= query.timeAfter.Value);
            }
            
            if (query.timeBefore.HasValue)
            {
                filtered = filtered.Where(m => m.createdTime <= query.timeBefore.Value);
            }
            
            // 位置过滤
            if (query.locationCenter.HasValue && query.locationRadius.HasValue)
            {
                var center = query.locationCenter.Value;
                var radius = query.locationRadius.Value;
                filtered = filtered.Where(m => Vector3.Distance(m.location, center) <= radius);
            }
            
            // 参与者过滤
            if (query.participantFilter != null && query.participantFilter.Count > 0)
            {
                filtered = filtered.Where(m => m.participants != null && 
                    query.participantFilter.Any(p => m.participants.Contains(p)));
            }
            
            return filtered.ToList();
        }
        
        /// <summary>
        /// 从事件更新空间记忆
        /// </summary>
        private void UpdateSpatialMemoryFromEvent(AgentEvent agentEvent)
        {
            try
            {
                // 确定空间位置
                var locationPath = DetermineLocationPath(agentEvent.location, agentEvent.locationName);
                
                // 更新空间信息
                if (!string.IsNullOrEmpty(agentEvent.subject))
                {
                    SpatialMemory.UpdateAgentLocation(agentEvent.subject, locationPath, agentEvent.location);
                }
                
                // 添加事件相关的对象信息
                if (agentEvent.eventType == EventType.Interaction && !string.IsNullOrEmpty(agentEvent.objectEntity))
                {
                    SpatialMemory.UpdateObjectLocation(agentEvent.objectEntity, locationPath, agentEvent.location);
                }
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"[MemorySystem] Error updating spatial memory: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 确定位置路径
        /// </summary>
        private string DetermineLocationPath(Vector3 location, string locationName)
        {
            if (!string.IsNullOrEmpty(locationName))
            {
                return locationName;
            }
            
            // 简化的位置路径生成
            return $"area_{Mathf.RoundToInt(location.x / 10f)}_{Mathf.RoundToInt(location.z / 10f)}";
        }
        
        /// <summary>
        /// 清理过期记忆
        /// </summary>
        public void CleanupExpiredMemories()
        {
            try
            {
                var expiredMemories = AssociativeMemory.GetExpiredMemories();
                
                foreach (var memory in expiredMemories)
                {
                    AssociativeMemory.RemoveMemory(memory.nodeId);
                    OnMemoryExpired?.Invoke(memory.nodeId);
                }
                
                if (enableMemoryLogging && expiredMemories.Count > 0)
                {
                    Debug.Log($"[MemorySystem] Cleaned up {expiredMemories.Count} expired memories");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError($"[MemorySystem] Error cleaning up expired memories: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 获取记忆统计信息
        /// </summary>
        public string GetMemoryStats()
        {
            var totalMemories = AssociativeMemory.GetMemoryCount();
            var spatialNodes = SpatialMemory.GetNodeCount();
            
            return $"Total Memories: {totalMemories}, Spatial Nodes: {spatialNodes}, Stored: {totalMemoriesStored}, Retrieved: {totalMemoriesRetrieved}";
        }
        
        /// <summary>
        /// 重置记忆统计
        /// </summary>
        public void ResetMemoryStats()
        {
            totalMemoriesStored = 0;
            totalMemoriesRetrieved = 0;
        }
        
        /// <summary>
        /// 加载持久化记忆
        /// </summary>
        private void LoadPersistedMemories()
        {
            if (dataPersistence != null)
            {
                try
                {
                    dataPersistence.LoadMemories(this);
                    
                    if (enableMemoryLogging)
                    {
                        Debug.Log("[MemorySystem] Loaded persisted memories");
                    }
                }
                catch (Exception ex)
                {
                    Debug.LogWarning($"[MemorySystem] Error loading persisted memories: {ex.Message}");
                }
            }
        }
        
        /// <summary>
        /// 保存记忆到持久化
        /// </summary>
        private void SaveMemoriesToPersistence()
        {
            if (dataPersistence != null)
            {
                try
                {
                    dataPersistence.SaveMemories(this);
                    
                    if (enableMemoryLogging)
                    {
                        Debug.Log("[MemorySystem] Saved memories to persistence");
                    }
                }
                catch (Exception ex)
                {
                    Debug.LogWarning($"[MemorySystem] Error saving memories to persistence: {ex.Message}");
                }
            }
        }
        
        /// <summary>
        /// 设置记忆系统参数
        /// </summary>
        public void SetMemoryParameters(int maxMemories, float decayRate, float[] weights)
        {
            maxAssociativeMemories = maxMemories;
            memoryDecayRate = decayRate;
            
            if (weights.Length >= 3)
            {
                recencyWeight = weights[0];
                importanceWeight = weights[1];
                relevanceWeight = weights[2];
            }
            
            AssociativeMemory.SetMaxCapacity(maxMemories);
        }
    }
}